package com.sunlands.zlcx.usercenter.controller;

import com.sunlands.zlcx.usercenter.client.DeskMatePushService;
import com.sunlands.zlcx.usercenter.client.MessageService;
import com.sunlands.zlcx.usercenter.client.UserFriendsService;
import com.sunlands.zlcx.usercenter.client.bean.PushDTO;
import com.sunlands.zlcx.usercenter.common.annotation.AutoLog;
import com.sunlands.zlcx.usercenter.domain.InviteCodeDO;
import com.sunlands.zlcx.usercenter.domain.UsersDO;
import com.sunlands.zlcx.usercenter.exception.CheckParamException;
import com.sunlands.zlcx.usercenter.exception.GlobalExceptionHandler;
import com.sunlands.zlcx.usercenter.service.UsersInviteServiceImpl;
import com.sunlands.zlcx.usercenter.service.UsersServiceImpl;
import com.sunlands.zlcx.usercenter.service.VipUserServiceImpl;
import com.sunlands.zlcx.usercenter.vo.*;
import com.sunlands.zlcx.usercenter.vo.feign.MessageVO;
import com.sunlands.zlcx.usercenter.vo.response.BusinessResult;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.sunlands.zlcx.usercenter.vo.CommonResultMessage.*;

/**
 * @author shixiaopeng
 */
@SuppressWarnings("unused")
@Api(tags = "8、邀请相关", position = 8)
@ApiResponses(value = {@ApiResponse(code = 400, response = GlobalExceptionHandler.class, message = "数据校验失败"), @ApiResponse(code = 500, response = GlobalExceptionHandler.class, message = "内部错误")})
@Slf4j
@RestController
@RequestMapping("/invite")
public class UsersInviteController implements AuthSupport {

    @Autowired
    private UsersInviteServiceImpl usersInviteService;

    @Autowired
    private DeskMatePushService deskMatePushService;

    @Autowired
    protected MessageService messageService;

    @Autowired
    UsersServiceImpl usersService;

    @Autowired
    VipUserServiceImpl vipUserService;

    @Autowired
    UserFriendsService tzUserFriendsService;

    @Resource(name = "vipChargingExecutor")
    private ThreadPoolTaskScheduler vipChargingExecutor;

    @Resource(name = "gyfTaskExecutor")
    AsyncTaskExecutor gyfTaskExecutor;

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @AutoLog
    @ApiOperation(value = "邀请规则和赠送时长--APP调用")
    @PreAuthorize("isAuthenticated()")
    @GetMapping("/rule")
    public BusinessResult<UserInviteRuleVO> getInviteRule() {
        Long userId = currentUserId();
        UserInviteRuleVO rule = usersInviteService.getRule();
        long count = usersInviteService.getCount(userId, sdf.format(new Date()));
        if (count > 0) {
            rule.setNoVipCodeCount(count);
        }
        return BusinessResult.createSuccessInstance(rule);
    }


    @AutoLog
    @ApiOperation(value = "获取邀请码列表--APP调用")
    @PreAuthorize("isAuthenticated()")
    @GetMapping("/code/list")
    public BusinessResult<InviteInfoVO> getInviteCode() {
        UsersDO usersDO = currentUsers(usersService);
        List<InviteCodeDO> inviteCodeDOS = usersInviteService.getCode(usersDO.getId(), sdf.format(new Date()));
        UserInviteRuleVO rule = usersInviteService.getRule();
        List<InviteCodeVO> result = InviteCodeVO.fromDO(inviteCodeDOS).stream().map(inviteCodeVO -> {
            inviteCodeVO.setLink(rule.getLink() + inviteCodeVO.getCode());
            Long inviteUserId = inviteCodeVO.getInviteUserId();
            if (Objects.isNull(inviteUserId)) {
                inviteCodeVO.setIsUsed(false);
            } else {
                inviteCodeVO.setIsUsed(true);
            }
            inviteCodeVO.setUserName(usersDO.getName());
            return inviteCodeVO;
        }).collect(Collectors.toList());

        InviteInfoVO inviteInfoVO = new InviteInfoVO();
        inviteInfoVO.setInviteCodeList(result);
        inviteInfoVO.setGiveMinutes(rule.getGiveMinutes());
        return BusinessResult.createSuccessInstance(inviteInfoVO);
    }

    @AutoLog
    @ApiOperation(value = "验证邀请码,-1已过期，1已使用，0未使用")
    @PreAuthorize("isAuthenticated()")
    @GetMapping("/check/{code}")
    public BusinessResult<Integer> checkInviteCode(@ApiParam(value = "邀请码") @PathVariable String code) {
        InviteCodeDO codeDO = usersInviteService.findCode(code, sdf.format(new Date()));
        if (Objects.isNull(codeDO)) {
            return BusinessResult.createSuccessInstance(-1);
        }
        if (Objects.nonNull(codeDO.getInviteUserId())) {
            return BusinessResult.createSuccessInstance(1);
        }
        return BusinessResult.createSuccessInstance(0);
    }

    @AutoLog
    @ApiOperation(value = "使用关联邀请码--APP调用")
    @PreAuthorize("isAuthenticated()")
    @GetMapping("/relation/{code}")
    public BusinessResult<InviteCodeVO> relationInviteCode(@ApiParam(value = "邀请码") @PathVariable String code) {
        String today = sdf.format(new Date());
        UsersDO usersDO = currentUsers(usersService);
        Date createTime = usersDO.getCreateTime();
        if ((System.currentTimeMillis() - createTime.getTime()) > 24 * 60 * 60 * 1000) {
            return BusinessResult.createInstance(NO_NEW_USER);
        }
        Long userId = usersDO.getId();
        //校验，一个被邀请用户，只能使用一个邀请码
        InviteCodeDO inviteCodeDO = usersInviteService.findByInviteUserId(userId);
        if (Objects.nonNull(inviteCodeDO)) {
            return BusinessResult.createInstance(USED_INVITE_CODE);
        }
        InviteCodeDO codeDO = usersInviteService.findCode(code);
        if (Objects.isNull(codeDO)) {
            return BusinessResult.createInstance(INVITE_CODE_NO_VALID);
        }
        BusinessResult<InviteCodeVO> result = usersInviteService.relation(codeDO, userId, code, today);
        InviteCodeVO codeVO = result.getData();
        if (Objects.isNull(codeVO)) {
            return result;
        }

        //异步处理
        gyfTaskExecutor.execute(() -> {
            //赠送时长
            vipUserService.giveMinutes(codeDO);

            //结伴邀请
            //被邀请人
            UsersVO usersVO = usersService.findOne(userId);
            //邀请人
            UsersVO usersMaster = usersService.findOne(codeDO.getUserId());

            //邀请人申请
            tzUserFriendsService.applyBindFriends(codeDO.getUserId(), userId, String.format("来自好友%s邀请", usersMaster.getName()), "你使用了TA的邀请码", 2);
            //被邀请人申请
            tzUserFriendsService.applyBindFriends(userId, codeDO.getUserId(), String.format("来自好友%s邀请", usersVO.getName()), "通过你的邀请码" + code.toUpperCase() + "注册", 2);

            //发送push和消息
            //邀请人
            PushDTO pushMsg = PushDTO.builder().ids(Collections.singletonList(codeVO.getUserId().toString())).type(PushDTO.TypeEnum.USER.code).title("邀请成功").content(usersVO.getName() + "使用你的邀请码加入了同桌").build();
            deskMatePushService.push(pushMsg);

            MessageVO messageVO = MessageVO.builder().businessId(codeVO.getUserId() + "").userIds(Collections.singletonList(codeVO.getUserId())).content(usersVO.getName() + "邀请成功，获赠" + codeDO.getGiveMinutes() + "分钟连麦时长").type("760").build();
            messageService.sendMessage(messageVO);
        });

        //获得免费时长后，异步实时扣费，马上触发扣费切换
        vipChargingExecutor.execute(() -> vipUserService.preReduceTime(userId));
        return BusinessResult.createSuccessInstance(codeVO);
    }

    @AutoLog
    @ApiOperation(value = "邀请码信息--h5调用")
    @GetMapping("/info/{code}")
    public BusinessResult<InviteCodeH5VO> info(@ApiParam(value = "邀请码") @PathVariable String code) {
        code = code.trim();
        String today = sdf.format(new Date());
        InviteCodeDO codeDO = usersInviteService.findCode(code);
        if (Objects.isNull(codeDO)) {
            throw new CheckParamException("邀请码已过期/不存在");
        }
        UsersVO users = usersService.find(codeDO.getUserId());

        long secondsSurplusToday = 86400 - DateUtils.getFragmentInSeconds(Calendar.getInstance(), Calendar.DATE);
        InviteCodeH5VO h5VO = InviteCodeH5VO.builder()
                .avatarUrl(users.getAvatarUrl())
                .code(code)
                .isUsed(Objects.nonNull(codeDO.getInviteUserId()))
                .validTime(today.equals(sdf.format(codeDO.getCreateTime())) ? secondsSurplusToday : 0)
                .userName(users.getName())
                .userId(users.getId())
                .build();

        return BusinessResult.createSuccessInstance(h5VO);
    }

}

